import re
from rest_framework_jwt.settings import api_settings
from rest_framework import serializers
from .models import User
from django_redis import get_redis_connection
from celery_tasks.email.tasks import send_verify_email

class CreateUserSerializer(serializers.ModelSerializer):
    """註冊序列化器"""

    # 序列化器需要校驗所有字段['id','username','password','password2','mobile','sms_code','allow']
    # 需要校驗的字段['username','password','password2','mobile','sms_code','allow']
    # 模型中已存在的字段:['id','username','password','mobile']

    # 需要序列化的字段['id','user','mobile','token']
    # 需要反序列化['username','password','password2','mobile','sms_code','allow']
    password2  = serializers.CharField(label='確認密碼',write_only=True)
    sms_code  = serializers.CharField(label='驗證碼',write_only=True)
    allow = serializers.CharField(label='同意協議',write_only=True) #前端同意協議後傳來的是true首字母小寫
    token= serializers.CharField(label = 'token',read_only=True)

    class Meta:
        model = User # 從user模型中映射序列化器字段
        fields = ['id','username','password','password2','mobile','sms_code','allow','token']
        extra_kwargs = { #修改字段選項
            'username': {
                'min_length': 5,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许5-20个字符的⽤户名',
                    'max_length': '仅允许5-20个字符的⽤户名',
                }
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码',
                }
            }
        }

    def validate_mobile(self, value):
        # 單獨校驗手機號
        if not re.match(r'1[3-9]\d{9}$',value):
            raise serializers.ValidationError('手機號格式有誤')

        return value

    def validate_allow(self, value):
        if value != 'true':
            raise serializers.ValidationError('請同意協議')

    def validate(self, attrs):
        """校驗兩個密碼是否相同"""
        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError('兩個密碼不一致')

        # 校驗驗證碼
        redis_conn = get_redis_connection('verify_codes')
        mobile = attrs['mobile']
        real_sms_code = redis_conn.get('sms_%s'% mobile)

        # 向redis存儲數據時都是以字符串存儲的,取出來都是bytes類型

        if real_sms_code is None or attrs['sms_code'] != real_sms_code.decode():
            raise serializers.ValidationError('驗證碼錯誤')
        return attrs

    def create(self, validated_data):
        # 把不需要存儲的 password2,sms_code,allow 從字段中刪除
        del validated_data['password2']
        del validated_data['sms_code']
        del validated_data['allow']
        # 取密碼
        password = validated_data.pop('password')
        # 穿件用戶模型對象,給模型中的 username和mobile屬性賦值
        user = User(**validated_data)
        user.set_password(password) # 把密碼加密後再賦值給user的password屬性
        user.save() #　存儲到數據庫



        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER # 引用jwt中的JWT_PAYLOAD_HANDLER函數
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER # 引用jwt中的JWT_ENCODE_HANDLER函數,生成jwt

        payload = jwt_payload_handler(user) # 根據user生成用戶相關的載荷
        token = jwt_encode_handler(payload) #　傳入載荷生成完整的jwt

        user.token = token




        return user

class UserDetailSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ['id','username','mobile','email','email_active']

class EmailSerializer(serializers.ModelSerializer):
    """更新邮箱序列化器"""
    class Meta:
        model = User
        fields = ['id','email']
        extra_kwargs = {
            'email':{
                'required':True
            }
        }

    def update(self,instance,validated_data):
        """重写此方法目录不是为了修改,而是借用此时机 发激活邮箱"""
        # super(EmailSerializer,self).update(instance,validated_data)
        instance.email = validated_data.get('email')
        instance.save()

        # 将来
        #
        #
        # 需要在此继续写发邮件的功能
        # 'http://www.meiduo.site:8080/success_verify_email.html?token=user.id
        verify_url =instance.generate_email_verify_url()
        send_verify_email.delay(instance.email,verify_url = verify_url)

        return instance













